﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Qianke.Core.Common
{
    public class EnumItem
    {
        public long Id { set; get; }

        public string Name { set; get; }
    }

    public static class EnumHelper
    {
        public static string GetEnumDescription<TEnum>(this TEnum enumVal)
        {
            try
            {
                Type enumType = enumVal.GetType();
                if (!enumType.IsEnum)
                    throw new ArgumentException("enumItem requires a Enum ");
                object[] objs = enumType.GetField(enumVal.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
                return objs == null || objs.Length == 0 ? enumVal.ToString() : (objs[0] as DescriptionAttribute).Description;
            }
            catch (Exception)
            {
                return "";
            }
        }

        /// <summary>
        /// 获取多个值
        /// </summary>
        /// <typeparam name="TEnum"></typeparam>
        /// <param name="enumVal"></param>
        /// <returns></returns>
        public static List<string> GetEnumDescriptions<TEnum>(this TEnum enumVal)
        {
            var tType = enumVal.GetType();
            var nVal = System.Enum.Format(tType, enumVal, "d").ToInt(0);
            return System.Enum.GetValues(tType).Cast<TEnum>().Where(u =>
            {
                var nu = System.Enum.Format(tType, u, "d").ToInt(0);
                return (nVal & nu) == nu;
            }).Select(u => u.GetEnumDescription()).ToList();
        }

        public static string GetEnumDescriptions<TEnum>(this TEnum enumVal, string splitSymbol)
        {
            return string.Join(splitSymbol, enumVal.GetEnumDescriptions());
        }


        public static string GetEnumDescription(this object enumVal, Type enumType)
        {
            if (!enumType.IsEnum)
                throw new ArgumentException("enumItem requires a Enum ");
            var field = enumType.GetField(enumVal.ToString());
            if (field == null) return "";
            object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
            return objs == null || objs.Length == 0 ? enumVal.ToString() : (objs[0] as DescriptionAttribute).Description;
        }


        public static string GetDescription<TModel>(this TModel model, string properName)
        {
            return typeof(TModel).GetDescription(properName);
        }

        public static string GetDescription(this Type modelType, string properName)
        {
            var attrArry = modelType.GetProperty(properName).GetCustomAttributes(typeof(DisplayNameAttribute), false);
            if (attrArry.Length == 0) return string.Empty;
            return (attrArry[0] as DisplayNameAttribute).DisplayName;
        }

        public static string GetDescription<TModel>(this TModel model)
        {
            var attrArry = model.GetType().GetCustomAttributes(typeof(DisplayNameAttribute), false);
            if (attrArry.Length == 0) return string.Empty;
            return (attrArry[0] as DisplayNameAttribute).DisplayName;
        }

        private static Regex _regGetField = new Regex("[a-zA-Z0-9_]+");

        public static string GetMemberName(this LambdaExpression expGetVal)
        {
            var field = expGetVal.Body.ToString().Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries)[1];
            return _regGetField.Match(field).ToString();
        }

        /// <summary>
        /// 获取Lambda表达式 指定从成员属性值  
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TR"></typeparam>
        /// <param name="model">模型</param>
        /// <param name="expGetVal">Lambda表达式</param>
        /// <returns></returns>
        public static TR GetValByExpression<TModel, TR>(this TModel model, Expression<Func<TModel, TR>> expGetVal)
        {
            return expGetVal.Compile().Invoke(model);
        }

        public static List<EnumItem> GetEnumList<TEnum>()
        {
            return System.Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Select(u => new EnumItem() { Id = Convert.ToInt64(System.Enum.Format(typeof(TEnum), u, "d")), Name = u.GetEnumDescription() }).ToList();
        }

        /// <summary>
        /// 从数字中获取枚举列表
        /// </summary>
        /// <typeparam name="TEnum"></typeparam>
        /// <param name="num"></param>
        public static List<EnumItem> GetEnumListXOR<TEnum>(this TEnum value) where TEnum : System.Enum
        {
            Type enumType = typeof(TEnum);
            if (!enumType.IsEnum)
                throw new ArgumentException("enumItem requires a Enum ");
            var lval = Convert.ToInt64(value);
            return System.Enum.GetValues(enumType).Cast<TEnum>()
                .Where(u => (lval & Convert.ToInt64(u)) == Convert.ToInt64(u))
                .Select(u => new EnumItem { Id = Convert.ToInt64(u), Name = u.GetEnumDescription() })
                .ToList();
        }


        public static List<EnumItem> GetEnumList<TEnum>(this TEnum v)
        {
            return GetEnumList<TEnum>();
        }

    }
}
